import axios, { AxiosInstance, AxiosResponse, InternalAxiosRequestConfig } from 'axios'
import { nativeHandler } from 'qmp-native'
import { Toast } from 'qmp-component'
import { IResponseData, IResponseError } from '@/types/request-base'
const { programmeFlag } = require('@/config/settings') // 当前项目名称
import { tansParams } from '@/utils'
import cache from '@/utils/cache'
import errorCode from '@/utils/errorCode'

// 提示
Toast.allowMultiple(false)
let count = 0
function loading(cnf: any) {
  if (!(cnf && cnf.loading)) return
  count++
  Toast.loading({
    message: cnf.message || '加载中...',
    forbidClick: true,
    loadingType: 'spinner',
    duration: 0
  })
}
function clear(cnf: any) {
  if (!(cnf && cnf.loading)) return
  count--
  if (count <= 0) {
    Toast.clear()
    count = 0
  }
}
const excludeApis = ['/data-dict/', '/select-service', '/qmp'] // 外部api地址

// const BASE = require('@/config/index')
const service: AxiosInstance = axios.create({
  //   baseURL: process.env.QMP_EVN === 'development' ? '' : BASE.baseUrl,
  timeout: 30000
})

service.interceptors.request.use(
  async (config: InternalAxiosRequestConfig) => {
    const reqHeader: any = config.headers || {}
    // 是否需要设置 token
    const isToken = reqHeader.isToken !== false
    // 是否需要防止数据重复提交
    const isRepeatSubmit = reqHeader.repeatSubmit !== false

    const { token } = await nativeHandler()
    if (token && isToken) {
      config.headers['Authorization'] = `${token}` // 让每个请求携带自定义token 请根据实际情况自行修改
    }

    // get请求映射params参数
    if (config.method === 'get' && config.params) {
      let url = config.url + '?' + tansParams(config.params)
      url = url.slice(0, -1)
      config.params = {}
      config.url = url
    }
    if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) {
      const requestObj = {
        url: config.url,
        data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data,
        time: new Date().getTime()
      }
      const sessionObj = cache.session.getJSON('sessionObj')
      if (sessionObj === undefined || sessionObj === null || sessionObj === '') {
        cache.session.setJSON('sessionObj', requestObj)
      } else {
        const s_url = sessionObj.url // 请求地址
        const s_data = sessionObj.data // 请求数据
        const s_time = sessionObj.time // 请求时间
        const interval = 1000 // 间隔时间(ms)，小于此时间视为重复提交
        if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) {
          const message = '数据正在处理，请勿重复提交'
          console.warn(`[${s_url}]: ` + message)
          return Promise.reject(new Error(message))
        } else {
          cache.session.setJSON('sessionObj', requestObj)
        }
      }
    }

    if (config.loading) {
      loading(config)
    }

    const flag = excludeApis.some((p) => config.url && config.url.indexOf(p) === 0)
    // 本地开发时匹配本地代理的接口基础地址
    if (process.env.QMP_EVN === 'development') {
      config.baseURL = flag ? '' : `/${config.projectName || programmeFlag}`
      return config
    }
    // 非本地开发时，通过底座方法获取当前对应应用、对应环境的接口基础地址(实现一个包可用于移动门户或UU协同的正式和测试环境)
    const { data } = await nativeHandler('getServerUrl', '')
    config.baseURL = flag ? data : data + (config.projectName || programmeFlag)

    return config
  },
  (error) => {
    return Promise.reject(error)
  }
)

// response interceptor
service.interceptors.response.use(
  (response): Promise<AxiosResponse<IResponseData>> => {
    const resConfig = response.config
    clear(resConfig)

    const res = response.data
    const status = Number(response.status) || 200
    const message = res.msg || '未知原因，请联系管理员'

    if (status !== 200 || res.success === 0) {
      if (resConfig?.errorShow === true) {
        Toast.fail(message)
      }
      return Promise.reject(message)
    }

    if (resConfig.responseType === 'blob') {
      return response.data
    }
    return Promise.resolve(response.data)
  },
  async (error): Promise<IResponseError> => {
    const errorConfig: any = error.config
    clear(errorConfig)

    let { message } = error
    if (error.response) {
      const { data, status } = error.response
      message = errorCode[`${status}`] || errorCode['default']
      if (data && data.msg) {
        message = data.msg
      }
      if (status === 401 || ['401', 401].includes(data.code)) {
        // 登录失效
        Toast('登录已失效，请重新登录。(您的账号可能已在别处登录，请妥善保存密码，勿与他人共用账号。')
        return Promise.reject('登录失效')
      }
    } else {
      if (message === 'Network Error') {
        message = '后端接口连接异常'
      } else if (message.includes('timeout')) {
        message = '系统接口请求超时'
      } else if (message.includes('Request failed with status code')) {
        message = '系统接口' + message.substr(message.length - 3) + '异常'
      } else {
        message = '服务端异常'
      }
    }
    if (errorConfig?.errorShow === true) {
      Toast.fail(message)
    }
    return Promise.reject(error)
  }
)

export default service
